﻿@inherits AntDesignTestBase

@code {
    AntDesign.Internal.TextAreaInfo _textAreaInfo = new AntDesign.Internal.TextAreaInfo
    {
        LineHeight = 10,
        PaddingTop = 1,
        PaddingBottom = 1,
        BorderBottom = 1,
        BorderTop = 1
    };

    private void JSCommonMock()
    {
        JSInterop.SetupVoid(JSInteropConstants.InputComponentHelper.DisposeResizeTextArea, _ => true);
    }

    [Fact]
    public async Task TextArea_OnPressEnter_Should_Trigger_Callback()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        var onPressEnterInvoked = false;
        Action<PressEnterEventArgs> action = (args) => { onPressEnterInvoked = true; };
        var cut = Render<AntDesign.TextArea>(
            @<AntDesign.TextArea OnPressEnter="@(action)" />
        );
        
        //Act
        var textArea = cut.Find("textarea");
        await textArea.KeyPressAsync(new KeyboardEventArgs { Code = "Enter" });
        
        //Assert
        onPressEnterInvoked.Should().BeTrue();
    }

    [Fact]
    public async Task TextArea_PreventLineBreak_Should_Not_Add_NewLine()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        var initialText = "test";
        Action<PressEnterEventArgs> action = (args) => { args.PreventLineBreak(); };
        var cut = Render<AntDesign.TextArea>(
            @<AntDesign.TextArea Value="@initialText" OnPressEnter="@(action)" />
        );
        
        //Act
        var textArea = cut.Find("textarea");
        await textArea.KeyPressAsync(new KeyboardEventArgs { Code = "Enter" });
        var newText = initialText + "\r\n";
        textArea.Input(newText);
        textArea.Change(newText);
        
        //Assert
        cut.Instance.Value.Should().Be(initialText);
    }

    [Fact]
    public async Task TextArea_OnPressEnter_Should_Add_NewLine_When_Enter_Pressed_without_calling_PreventLineBreak()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        var initialText = "test";
        var onPressEnterInvoked = false;
        Action<PressEnterEventArgs> action = (args) => { onPressEnterInvoked = true; };
        var cut = Render<AntDesign.TextArea>(
            @<AntDesign.TextArea Value="@initialText" OnPressEnter="@(action)" />
        );
        
        //Act
        var textArea = cut.Find("textarea");
    
       await textArea.KeyPressAsync(new KeyboardEventArgs { Code = "Enter" });
        
        
        var newText = initialText + "\r\n";
        textArea.Input(newText);
        textArea.Change(newText);

        var actualValue = cut.Instance.Value;
        onPressEnterInvoked.Should().BeTrue();
        actualValue.Should().Be(newText);
    }

    [Fact]
    public async Task TextArea_OnPressEnter_Should_Not_Trigger_On_Other_Keys()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        var onPressEnterInvoked = false;
        Action<PressEnterEventArgs> action = (args) => { onPressEnterInvoked = true; };
        var cut = Render<AntDesign.TextArea>(
            @<AntDesign.TextArea OnPressEnter="@(action)" />
        );
        
        //Act
        var textArea = cut.Find("textarea");
        await textArea.KeyPressAsync(new KeyboardEventArgs { Code = "KeyA" });
        
        //Assert
        onPressEnterInvoked.Should().BeFalse();
    }

    [Fact]
    public async Task TextArea_OnPressEnter_Should_Provide_KeyboardEventArgs()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        PressEnterEventArgs? capturedArgs = null;
        Action<PressEnterEventArgs> action = (args) => { capturedArgs = args; };
        var cut = Render<AntDesign.TextArea>(
            @<AntDesign.TextArea OnPressEnter="@(action)" />
        );
        
        //Act
        var textArea = cut.Find("textarea");
        await textArea.KeyPressAsync(new KeyboardEventArgs { Code = "Enter", CtrlKey = true });
        
        //Assert
        capturedArgs.Should().NotBeNull();
        capturedArgs!.Code.Should().Be("Enter");
        capturedArgs.CtrlKey.Should().BeTrue();
    }

    [Fact]
    public void TextArea_ShowCount_shows_initial_value()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
        .SetResult(_textAreaInfo);
        string value = "0123456789";
        var cut = Render(
    @<AntDesign.TextArea ShowCount MaxLength=100 Value=@value />);
        //Act
        var divWrapper = cut.Find("div");
        var attribute = divWrapper.GetAttribute("data-count");

        //Assert
        attribute.Should().Be($"{value.Length} / 100");
    }

    [Fact]
    public void TextArea_ShowCount_without_maxlength()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
    .SetResult(_textAreaInfo);
        string value = "0123456789";
        var cut = Render(
    @<AntDesign.TextArea ShowCount Value=@value />);
        //Act
        var divWrapper = cut.Find("div");
        var attribute = divWrapper.GetAttribute("data-count");

        //Assert
        attribute.Should().Be($"{value.Length}");
    }

    //Check wrapper marks as disabled when TextArea disabled state
    [Fact]
    public void TextArea_Wrapper_Disabled()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
        .SetResult(_textAreaInfo);
        string value = "0123456789";
        var cut = Render(@<AntDesign.TextArea ShowCount Value=@value Disabled/>);
        //Act
        var span= cut.Find("span");
        //Assert
        span.ClassList.Should().Contain("ant-input-affix-wrapper-disabled");
    }

    [Fact]
    public void TextArea_ShowCount_increase()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        string value = "";
        string newValue = "newValue";
        var cut = Render<AntDesign.TextArea>(@<AntDesign.TextArea ShowCount MaxLength=100 Value=@value DebounceMilliseconds="0" />);
        //Act
        cut.Find("textarea").Input(newValue);
        cut.Find("textarea").KeyUp(String.Empty);
        cut.Render();
        var divWrapper = cut.Find("div");
        var attribute = divWrapper.GetAttribute("data-count");
        //Assert
        attribute.Should().Be($"{newValue.Length} / 100");
    }

    [Fact]
    public void TextArea_ReadOnly_creates_attribute()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        var cut = Render<AntDesign.TextArea>(@<AntDesign.TextArea ReadOnly Value="@("0123456789")" />);
        //Act
        var textAreaElement = cut.Find("textarea");
        //Assert
        textAreaElement.HasAttribute("readonly");
    }

    [Fact]
    public void TextArea_Rows_creates_attribute()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        var cut = Render<AntDesign.TextArea>(@<AntDesign.TextArea Rows="1" Value="@("0123456789")" />);
        //Act
        var textAreaElement = cut.Find("textarea");
        //Assert
        textAreaElement.GetAttribute("rows").Should().Be("1");
    }

    [Fact]
    public void TextArea_MaxLength_Adds_Attribute_To_Textarea()
    {
        JSCommonMock();
        JSInterop
            .Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);

        var cut = Render<TextArea>(@<TextArea MaxLength="50" />);

        var textAreaElement = cut.Find("textarea");

        textAreaElement.Attributes.Single(x => x.Name.ToLowerInvariant() == "maxlength").Value.Should().Be("50");
    }

    [Fact]
    public void TextArea_MaxLength_Adds_Attribute_To_Textarea_After_Initial_Render()
    {
        JSCommonMock();
        JSInterop
            .Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);

        var cut = Render<TextArea>(@<TextArea />);

        cut.Find("textarea").Attributes.SingleOrDefault(x => x.Name.ToLowerInvariant() == "maxlength").Should().BeNull();

        cut.SetParametersAndRender(parameters => parameters.Add(x => x.MaxLength, 50));

        cut.WaitForAssertion(() => cut.Find("textarea").Attributes.Single(x => x.Name.ToLowerInvariant() == "maxlength").Value.Should().Be("50"));
    }

    @*[Fact]
	public void TextArea_Rows_creates_with_expected_height()
	{
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        uint rows = 4;
        double expectedHeight = rows * _textAreaInfo.LineHeight +
                            _textAreaInfo.PaddingTop +
                            _textAreaInfo.PaddingBottom +
                            _textAreaInfo.BorderBottom +
                            _textAreaInfo.BorderTop;
        var cut = Render<AntDesign.TextArea>(
        @<AntDesign.TextArea Rows="@rows"/>);
		//Act && Assert
        var textAreaElement = cut.Find("textarea");
        var styleAttribute = textAreaElement.GetAttribute("style");
        styleAttribute.Should().Contain($"height: {expectedHeight}px");
	}*@

    @*[Fact]
	public void TextArea_MinRows_creates_with_expected_height()
	{
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.RegisterResizeTextArea, _ => true)
            .SetResult(_textAreaInfo);
        uint rows = 4;
        double expectedHeight = rows * _textAreaInfo.LineHeight +
                            _textAreaInfo.PaddingTop +
                            _textAreaInfo.PaddingBottom +
                            _textAreaInfo.BorderBottom +
                            _textAreaInfo.BorderTop;
        var cut = Render<AntDesign.TextArea>(
        @<AntDesign.TextArea MinRows="@rows" Rows="1"/>);
		//Act && Assert
        var textAreaElement = cut.Find("textarea");
        var styleAttribute = textAreaElement.GetAttribute("style");
        styleAttribute.Should().Contain($"height: {expectedHeight}px");
	}*@

    [Fact]
    public void TextArea_AutoSize_is_true_when_MinRows_set()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.RegisterResizeTextArea, _ => true)
            .SetResult(_textAreaInfo);
        var cut = Render<AntDesign.TextArea>(@<AntDesign.TextArea MinRows="1" AutoSize="false" />);
        //Act && Assert
        cut.Instance.AutoSize.Should().BeTrue();
    }

    [Fact]
    public void TextArea_AutoSize_is_true_when_MaxRows_set()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.RegisterResizeTextArea, _ => true)
            .SetResult(_textAreaInfo);
        var cut = Render<AntDesign.TextArea>(@<AntDesign.TextArea MaxRows="4" AutoSize="false" />);
        //Act && Assert
        cut.Instance.AutoSize.Should().BeTrue();
    }

    @*[Fact]
	public void TextArea_MaxRows_will_take_precedence_over_Rows()
	{
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.RegisterResizeTextArea, _ => true)
            .SetResult(_textAreaInfo);
        uint rows = 4;
        double expectedHeight = rows * _textAreaInfo.LineHeight +
                            _textAreaInfo.PaddingTop +
                            _textAreaInfo.PaddingBottom +
                            _textAreaInfo.BorderBottom +
                            _textAreaInfo.BorderTop;

        var cut = Render<AntDesign.TextArea>(@<AntDesign.TextArea Rows="10" MaxRows="@rows"/>);
        //Act && Assert
         var textAreaElement = cut.Find("textarea");
        var styleAttribute = textAreaElement.GetAttribute("style");
        styleAttribute.Should().Contain($"height: {expectedHeight}px");
	}*@

    [Fact]
    public void TextArea_Class_Attribute_Is_Rendered()
    {
        //Arrange
        JSCommonMock();
        JSInterop.Setup<AntDesign.Internal.TextAreaInfo>(JSInteropConstants.InputComponentHelper.GetTextAreaInfo, _ => true)
            .SetResult(_textAreaInfo);
        string customClass = "custom-textarea-class";
        
        //Act
        var cut = Render<AntDesign.TextArea>(@<AntDesign.TextArea Class="@customClass" />);
        var textAreaElement = cut.Find("textarea");
        
        //Assert
        textAreaElement.ClassList.Should().Contain(customClass);
    }
}
